import datetime
import json
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect
from django.urls import reverse
from django.contrib.auth.hashers import make_password, check_password
from django.contrib.auth import models as auth_models
from stocksys import models as stocksys_models
from managersys.forms import LoginForms
from stocksys.stocksys_forms.config_forms import SYSConfigForms
from stocksys.stocksys_forms.message_form import SendMessageForms
from stocksys.stocksys_forms.stock_form import AddStockForms, DeleteStockForms, OrderStockForms, OrderCancelForms, \
    OpenInterestEditForms
from stocksys.views.data_logic import init_message, send_message_submit, send_email_message
from managersys import models as managersys_models


def check_login(func):
    """
    查看session值用来判断用户是否已经登录
    :param func:
    :return:
    """

    def warpper(request, *args, **kwargs):
        if request.session.get('username', False):
            return func(request, *args, **kwargs)
        else:
            return redirect(reverse('stocksys:stocksys_login'))

    return warpper


@check_login
def message(request):
    context = init_message(request)
    context['title'] = '站内信'
    messages = []
    messages_orm = managersys_models.Message.objects.filter(recive_user=request.session.get("id"))
    [messages.append({
        'id': message.id,
        'send_user': auth_models.User.objects.get(id=message.send_user).username,
        'create_time': message.create_time,
        'is_read': message.is_read,
        'content': message.content,
        'title': message.title,
    }) for message in messages_orm]
    context['messages'] = messages
    return render(request, "stocksys/user/user_message.html", context)


@check_login
def user_message_content(request, id):
    # 做个判断 请求类型
    if request.method == "GET":
        context = init_message(request)
        context['title'] = '信件详情'
        message = managersys_models.Message.objects.get(id=id)
        context['message'] = message
        return render(request, "stocksys/user/user_message_content.html", context)
    elif request.method == "POST":
        action = request.POST.get("action", default=False)  # 获取操作类型
        value = request.POST.get("value", default=False)  # 获取操作值
        message = managersys_models.Message.objects.get(id=id)
        if action == "is_read":
            value = True if value == 'true' else False
            message.is_read = value
            message.create_time = datetime.datetime.now()
            message.save()
        if action == "remove":
            message.delete()
        return JsonResponse({"state": 200})


@check_login
def send_message(request):
    if request.method == "POST":
        messange_forms = SendMessageForms(request.POST)
        if messange_forms.is_valid():
            to_user_name = messange_forms.cleaned_data['username']
            title = messange_forms.cleaned_data['title']
            use_email = messange_forms.cleaned_data['use_email']
            content = messange_forms.cleaned_data['content']
            # content = render(request, 'stocksys/message/急速拉升.html').content.decode('utf-8')
            from_user = auth_models.User.objects.get(id=request.session.get("id"))
            to_user = auth_models.User.objects.get(username=to_user_name)
            send_message_submit(from_user, to_user, title=title, content=content)
            if use_email:
                if to_user.email:
                    send_email_message(title, content, [to_user.email], "HTML")
                return JsonResponse({"state": 200, "info": 'send success'})
            return JsonResponse({"state": 200, "info": 'send success'})
        return JsonResponse({"state": 500, "info": '表单错误'.encode('utf-8')})
    else:
        context = init_message(request)
        context['title'] = '发送信件'
        return render(request, "stocksys/user/user_send_message.html", context)


@check_login
def mystock(request):
    user = auth_models.User.objects.get(id=request.session.get('id'))
    sysconf = stocksys_models.SysConf.objects.get(user=user)
    if request.method == "POST":
        add_mystock_forms = AddStockForms(request.POST)
        if add_mystock_forms.is_valid():
            stock_code = add_mystock_forms.cleaned_data['stock_code']
            stock_address_id = add_mystock_forms.cleaned_data['stock_address_id']
            exchange_address = stocksys_models.ExchangeAddress.objects.get(id=stock_address_id)
            stock = stocksys_models.Stock.objects.get(code=stock_code, exchange_address=exchange_address)
            stock_info = None
            if stocksys_models.StockInfo.objects.filter(stock=stock).count() == 0:
                stock_info = stocksys_models.StockInfo.objects.create(stock=stock, sysconf=sysconf)
                stock_info.save()
            else:
                stock_info = stocksys_models.StockInfo.objects.filter(stock=stock).first()
            if stocksys_models.MyStcock.objects.filter(stock=stock_info).count() == 0:
                stocksys_models.MyStcock.objects.create(stock=stock_info, sysconf=sysconf)
                return JsonResponse({'status': 200, 'info': 'add success'})
            else:
                return JsonResponse({'status': 500, 'info': 'stock had been added '})
    elif request.method == "DELETE":
        delete_mystock_forms = DeleteStockForms(request.DELETE)
        if delete_mystock_forms.is_valid():
            stock_code = delete_mystock_forms.cleaned_data['stock_code']
            stock_address_id = delete_mystock_forms.cleaned_data['stock_address_id']
            exchange_address = stocksys_models.ExchangeAddress.objects.get(id=stock_address_id)
            stock = stocksys_models.Stock.objects.get(code=stock_code, exchange_address=exchange_address)
            stock_info = stocksys_models.StockInfo.objects.filter(stock=stock).first()
            _mystock = stocksys_models.MyStcock.objects.filter(stock=stock_info)
            if _mystock.count() != 0:
                _mystock.delete()
                return JsonResponse({'status': 200, 'info': 'add success'})
            else:
                return JsonResponse({'status': 500, 'info': 'stock had been added '})
        return JsonResponse({'status': 500, 'info': 'add success'})

    elif request.method == "GET":
        context = init_message(request)
        context["title"] = "量化分析系统-我的自选"
        user = auth_models.User.objects.get(id=request.session.get('id'))
        sysconf = stocksys_models.SysConf.objects.get(user=user)
        mystock = stocksys_models.MyStcock.objects.filter(sysconf=sysconf)
        stock_infos = [x.stock for x in mystock]
        context["stock_infos"]=[]
        for stock_info in stock_infos:
            price_chg=stock_info.current_price-stock_info.yestoday_close
            context["stock_infos"].append({
                "stock":stock_info.stock,
                "price_chg":price_chg,
                "price_chg_percent":price_chg/stock_info.yestoday_close*100,
                "open":stock_info.today_open,
                "color":"danger" if price_chg>0 else "success",
                "current_price":stock_info.current_price,
                "volume":stock_info.volume,
                "money":stock_info.money,
            })
        context["now_year"] = int(datetime.datetime.now().strftime("%Y"))
        context["quant_start_date"] = sysconf.predict_start_time.strftime("%Y-%m-%d")
        context["quant_end_date"] = sysconf.predict_end_time.strftime("%Y-%m-%d")
        main_predict_model = stocksys_models.ManagedCode.objects.get(id=sysconf.main_model)

        context["quant_rule"] = main_predict_model.name
        context["predict_type"] = 'stock'
        # context["data_method"] = 'local'
        # context["data_method"] = 'jqdata'
        return render(request, "stocksys/user/user_stock_table.html", context)


def login(request):
    if request.session.get("username"):
        return redirect(reverse('stocksys:stocksys_index'))
    if request.method == "POST":
        login_froms = LoginForms(request.POST)
        if login_froms.is_valid():
            try:
                username = login_froms.cleaned_data['account']
                password = login_froms.cleaned_data['password']
                ip_address = login_froms.cleaned_data['ip_address']
                ip_city = login_froms.cleaned_data['ip_city']
                user = auth_models.User.objects.get(username=username)
                if user.check_password(password):
                    sysconf = stocksys_models.SysConf.objects.filter(user_id=user.id).first()
                    sysconf.login_ip_address = ip_address
                    sysconf.login_ip_city = ip_city
                    sysconf.save()
                    user.last_login = datetime.datetime.now()
                    request.session['username'] = user.username
                    request.session['id'] = user.id
                    return redirect(reverse('stocksys:stocksys_index'))
                else:
                    return redirect(reverse('stocksys:stocksys_login'))
            except Exception as e:
                print(e)
                return redirect(reverse('stocksys:stocksys_login'))
    if request.method == "GET":
        return render(request, "stocksys/user/user_login.html")

@check_login
def logout(request):
    request.session.clear()
    response = HttpResponse(json.dumps({"status": 0}))
    response.delete_cookie('username')
    return redirect(reverse('stocksys:stocksys_index'))


@check_login
def user_profile(request):
    context = init_message(request)
    context['title'] = '我的信息'
    user = auth_models.User.objects.get(id=request.session.get("id"))
    context['user'] = user
    sysconf = stocksys_models.SysConf.objects.get(user=user)
    context['sysconf'] = sysconf
    context['model'] = stocksys_models.ManagedCode.objects.get(id=sysconf.main_model)
    context['models'] = stocksys_models.ManagedCode.objects.filter(sysconf=sysconf)
    context['rule'] = stocksys_models.RuleInfo.objects.get(id=sysconf.main_rule)
    context['rules'] = stocksys_models.RuleInfo.objects.filter(sysconf=sysconf)
    return render(request, 'stocksys/user/user_profile.html', context)


@check_login
def user_settings(request):
    if request.method == "GET":
        context = init_message(request)
        context['title'] = '系统配置'
        return render(request, 'stocksys/user/user_settings.html', context)
    if request.method == "CONFIG":
        sys_config_forms = SYSConfigForms(request.CONFIG)
        if sys_config_forms.is_valid():
            user = auth_models.User.objects.get(id=request.session.get('id'))
            sysconf = stocksys_models.SysConf.objects.get(user=user)
            sysconf.my_capital = sys_config_forms.cleaned_data['my_capital']
            sysconf.sh_min_price = sys_config_forms.cleaned_data['sh_min_price']
            sysconf.sz_min_price = sys_config_forms.cleaned_data['sz_min_price']
            sysconf.predict_start_time = sys_config_forms.cleaned_data['predict_start_time']
            sysconf.predict_end_time = sys_config_forms.cleaned_data['predict_end_time']
            name_main_model = sys_config_forms.cleaned_data['main_model']
            main_model = stocksys_models.ManagedCode.objects.get(name=name_main_model)
            sysconf.main_model = main_model.id
            name_main_rule = sys_config_forms.cleaned_data['main_rule']
            main_rule = stocksys_models.RuleInfo.objects.get(name_en=name_main_rule)
            sysconf.main_rule = main_rule.id
            sysconf.sz_price = sys_config_forms.cleaned_data['sz_price']
            sysconf.sh_price = sys_config_forms.cleaned_data['sh_price']
            sysconf.stamp_tax = sys_config_forms.cleaned_data['stamp_tax']
            sysconf.transfer_feed = sys_config_forms.cleaned_data['transfer_feed']
            sysconf.save()
            return JsonResponse({"status": 200, "info": "success"})
    return JsonResponse({"status": 500, "info": "error"})


@check_login
def user_bonds(request):
    user = auth_models.User.objects.get(id=request.session.get('id'))
    sysconf = stocksys_models.SysConf.objects.get(user=user)
    if request.method == "GET":
        context = init_message(request)
        context['title'] = '量化分析系统-我的持仓'
        main_predict_model = stocksys_models.ManagedCode.objects.get(id=sysconf.main_model)
        open_intrests = stocksys_models.OpenInterests.objects.filter(sysconf=sysconf)
        open_intrests_info = []
        for open_intrest in open_intrests:
            price_chg = (open_intrest.stock.current_price - open_intrest.price)
            open_intrests_info.append({
                "price_chg": price_chg,
                "id": open_intrest.id,
                "number": open_intrest.number,
                "price": open_intrest.price,
                "price_chg_percent": price_chg / open_intrest.price * 100,
                "stock_name": open_intrest.stock.stock.name,
                "stock_code": open_intrest.stock.stock.code,
                "color": "danger" if price_chg > 0 else "success",
                "current_price": open_intrest.stock.current_price,
                "exchange_address_id": open_intrest.stock.stock.exchange_address.id,
                "buy_time": open_intrest.buy_time,
            })
        context["open_intrests"] = open_intrests_info
        context["now_year"] = int(datetime.datetime.now().strftime("%Y"))
        context["quant_start_date"] = sysconf.predict_start_time.strftime("%Y-%m-%d")
        context["quant_end_date"] = sysconf.predict_end_time.strftime("%Y-%m-%d")
        context["quant_rule"] = main_predict_model.name
        context["predict_type"] = 'stock'
        return render(request, "stocksys/user/user_bonds.html", context)
    elif request.method == "UPDATE":  # 卖出
        order_stock_forms = OrderStockForms(request.UPDATE)
        if order_stock_forms.is_valid():
            stock_code = order_stock_forms.cleaned_data['stock_code']
            stock_address_id = order_stock_forms.cleaned_data['stock_address_id']
            number = order_stock_forms.cleaned_data['number']
            price = order_stock_forms.cleaned_data['price']

            exchange_address = stocksys_models.ExchangeAddress.objects.get(id=stock_address_id)
            stock = stocksys_models.Stock.objects.get(code=stock_code, exchange_address=exchange_address)

            order_type = stocksys_models.OrderType.objects.get(order_type=1)  # 创建卖出类型订单
            order_state = stocksys_models.OrderState.objects.get(state=0)  # 创建未完成类型订单
            stock_info = stocksys_models.StockInfo.objects.filter(stock=stock, sysconf=sysconf)
            if stock_info.count() == 0:
                stock_info = stocksys_models.StockInfo.objects.create(stock=stock, sysconf=sysconf)
                stock_info.save()
            else:
                stock_info = stock_info.first()
            stocksys_models.CommitOrder.objects.create(stock_info=stock_info, price=price, number=number,
                                                       sysconf=sysconf,
                                                       state=order_state, order_type=order_type)
            return JsonResponse({'status': 200, 'info': 'Order success'})
    elif request.method == "PUT":  # 买入
        order_stock_forms = OrderStockForms(request.PUT)
        if order_stock_forms.is_valid():
            stock_code = order_stock_forms.cleaned_data['stock_code']
            stock_address_id = order_stock_forms.cleaned_data['stock_address_id']
            number = order_stock_forms.cleaned_data['number']
            price = order_stock_forms.cleaned_data['price']
            commission_charge = (number * price) * sysconf.sh_price
            if commission_charge < sysconf.sh_min_price:
                commission_charge = sysconf.sh_min_price  # 交易税
            if (sysconf.my_capital - (commission_charge + (number * price))) > 0:
                exchange_address = stocksys_models.ExchangeAddress.objects.get(id=stock_address_id)
                stock = stocksys_models.Stock.objects.get(code=stock_code, exchange_address=exchange_address)
                order_type = stocksys_models.OrderType.objects.get(order_type=0)  # 创建卖出类型订单
                order_state = stocksys_models.OrderState.objects.get(state=0)  # 创建未完成类型订单
                stock_info = stocksys_models.StockInfo.objects.filter(stock=stock, sysconf=sysconf)
                if stock_info.count() == 0:
                    stock_info = stocksys_models.StockInfo.objects.create(stock=stock, sysconf=sysconf)
                    stock_info.save()
                else:
                    stock_info = stock_info.first()
                stocksys_models.CommitOrder.objects.create(stock_info=stock_info, price=price, number=number,
                                                           sysconf=sysconf,
                                                           state=order_state, order_type=order_type)
                cost = (commission_charge + (number * price))
                print("每%s买入%s股 总共花费%s" % (price, number, cost))
                sysconf.my_capital -= cost
                sysconf.save()
                return JsonResponse({'status': 200, 'info': 'success'})
            return JsonResponse({'status': 500, 'info': 'Balance is not enough'})
            # TODO:买入委托处理
        return JsonResponse({'status': 500, 'info': 'Form check error'})
    elif request.method == "EDIT":
        order_cancel_forms = OpenInterestEditForms(request.EDIT)
        if order_cancel_forms.is_valid():
            open_interest_id = order_cancel_forms.cleaned_data['open_interest_id']
            price = order_cancel_forms.cleaned_data['price']
            open_interest = stocksys_models.OpenInterests.objects.get(id=open_interest_id)
            open_interest.price = price
            open_interest.save()
            return JsonResponse({'status': 200, 'info': 'success'})
        return JsonResponse({'status': 500, 'info': 'Form check error'})

        # TODO:卖出委托处理
        return JsonResponse({'status': 500, 'info': 'Form check error'})


@check_login
def user_order(request):
    user = auth_models.User.objects.get(id=request.session.get('id'))
    sysconf = stocksys_models.SysConf.objects.get(user=user)
    if request.method == "GET":
        context = init_message(request)
        context['title'] = '量化分析系统-我的订单'
        my_order = stocksys_models.CommitOrder.objects.filter(sysconf=sysconf).order_by("-state")
        context["orders"] = my_order
        return render(request, "stocksys/user/user_order.html", context)
    elif request.method == "DELETE":  # 撤单
        order_cancel = OrderCancelForms(request.DELETE)
        if order_cancel.is_valid():
            # 撤单前先归还用户资金
            order_id = order_cancel.cleaned_data['order_id']
            action = order_cancel.cleaned_data['action']
            if action == 'false':
                order_state = stocksys_models.OrderState.objects.get(state=0)  # 查找未完成订单
                commit_order = stocksys_models.CommitOrder.objects.filter(sysconf=sysconf, state_id=order_state.id)
                new_state = stocksys_models.OrderState.objects.get(state=2)  # 创建撤单类型订单
                for order in commit_order:
                    query_order = stocksys_models.CommitOrder.objects.get(order_id=order.order_id)
                    query_order.state = new_state
                    commission_charge = (query_order.number * query_order.price) * sysconf.sh_price
                    if commission_charge < sysconf.sh_min_price:
                        commission_charge = sysconf.sh_min_price  # 交易税
                    cost = commission_charge + (query_order.number * query_order.price)
                    sysconf.my_capital += cost
                    query_order.state = new_state
                    sysconf.save()
                    query_order.save()
                return JsonResponse({'status': 200, 'info': 'success'})
            else:
                order_state = stocksys_models.OrderState.objects.get(state=0)  # 查找未完成订单
                new_state = stocksys_models.OrderState.objects.get(state=2)  # 创建撤单类型订单
                try:
                    commit_order = stocksys_models.CommitOrder.objects.get(order_id=order_id, sysconf=sysconf,
                                                                           state_id=order_state.id)
                    commission_charge = (commit_order.number * commit_order.price) * sysconf.sh_price
                    if commission_charge < sysconf.sh_min_price:
                        commission_charge = sysconf.sh_min_price  # 交易税
                    cost = commission_charge + (commit_order.number * commit_order.price)
                    sysconf.my_capital += cost
                    print("总共花费%s" % (cost))
                    commit_order.state = new_state
                    commit_order.save()
                    sysconf.save()
                    return JsonResponse({'status': 200, 'info': "success"})
                except Exception as e:
                    print(e)
                    return JsonResponse({'status': 500, 'info': str(e)})
        return JsonResponse({'status': 500, 'info': 'Error'})


@check_login
def user_validate(request):
    if request.method == "POST":
        username = request.POST.get('username', default=None)
        if username:
            try:
                auth_models.User.objects.get(username=username)
                return HttpResponse("true")
            except Exception as e:
                return HttpResponse("false")
    return HttpResponse("false")
